﻿using System;
using Kaleida.ServiceMonitor.Framework;
using Kaleida.ServiceMonitor.Model.Runtime;
using Kaleida.ServiceMonitor.Operations.PreparedRequests;
using Kaleida.ServiceMonitor.Operations.ResponseHandlers;
using NUnit.Framework;

namespace Kaleida.UnitTests.Model.Runtime
{
    [TestFixture]
    public class DefaultStatePresentationTests
    {
        [Test]
        public void TestGet10FootSymbolWhenNotRunning()
        {
            var state = new MockMonitorState();
            var presentation = new DefaultStatePresentation(state);

            Assert.IsFalse(state.IsMonitoring);

            Assert.AreEqual("", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootSymbolWhenNotRunningAndHasErrors()
        {
            var state = new MockMonitorState {IsMonitoring = false};
            state.FailureCount++;

            var presentation = new DefaultStatePresentation(state);
            Assert.AreEqual(":-(", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootSymbolWhenRunningAndNoErrors()
        {
            var state = new MockMonitorState {IsMonitoring = true};

            var presentation = new DefaultStatePresentation(state);
            Assert.AreEqual(":-)", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootSymbolWhenRunningAndHasErrors()
        {
            var state = new MockMonitorState { IsMonitoring = true, FailureCount = 1 };

            var presentation = new DefaultStatePresentation(state);
            Assert.AreEqual(":-(", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootStatusMessage()
        {
            var state = new MockMonitorState();

            var presentation = new DefaultStatePresentation(state);
            Assert.AreEqual("", presentation.GetStateDetail());

            var dummyOp = new Operation(new HttpGet("http://localhost"), new DoNothing());

            state.IsMonitoring = true;
            state.AddError(new RequestErrorResult(dummyOp, new DateTime(2012, 1, 5), new DateTime(2012, 1, 5), new Exception("First Error")));
            Assert.AreEqual("1 error:\r\n    05/01/2012 00:00:00 First Error\r\n", presentation.GetStateDetail());
            state.AddError(new RequestErrorResult(dummyOp, new DateTime(2012, 1, 6), new DateTime(2012, 1, 6), new Exception("Second Error")));
            Assert.AreEqual("2 errors:\r\n    First:  05/01/2012 00:00:00 First Error\r\n    Latest: 06/01/2012 00:00:00 Second Error\r\n", presentation.GetStateDetail());
            state.AddError(new RequestErrorResult(dummyOp, new DateTime(2012, 1, 7), new DateTime(2012, 1, 7), new Exception("Third Error")));
            Assert.AreEqual("3 errors:\r\n    First:  05/01/2012 00:00:00 First Error\r\n    Latest: 07/01/2012 00:00:00 Third Error\r\n", presentation.GetStateDetail());
            state.IsMonitoring = false;
            Assert.AreEqual("3 errors:\r\n    First:  05/01/2012 00:00:00 First Error\r\n    Latest: 07/01/2012 00:00:00 Third Error\r\n", presentation.GetStateDetail());
        }
    }

    public class MockMonitorState : IMonitorState
    {
        public bool IsMonitoring { get; set; }
        public int FailureCount { get; set; }

        public Percentage SuccessRate { get; set; }

        public RequestErrorResult FirstFailureOrDefault { get; set; }
        public RequestErrorResult LatestFailureOrDefault { get; set; }

        public void AddError(RequestErrorResult error)
        {
            if (FirstFailureOrDefault == null)
                FirstFailureOrDefault = error;

            LatestFailureOrDefault = error;
            FailureCount++;
        }
    }

    internal static class TestHelper
    {
        internal static void IncrementErrorsCountBy(this MonitorState state, int count)
        {
            for (int i = 0; i < count; i++)
                state.FlagError();
        }

        internal static void FlagError(this MonitorState state)
        {
            var operation = new Operation(new HttpGet("http://locahost"), new DoNothing());
            state.AddResult(new RequestErrorResult(operation, DateTime.Now, DateTime.Now, new Exception("Dummy Error")));
        }
    }
}
